package com.jhf.youke.base.domain.service;

import com.jhf.youke.base.domain.converter.PermissionsConverter;
import com.jhf.youke.base.domain.exception.PermissionsException;
import com.jhf.youke.base.domain.gateway.PermissionsSetRepository;
import com.jhf.youke.base.domain.model.Do.PermissionsDo;
import com.jhf.youke.base.domain.gateway.PermissionsRepository;
import com.jhf.youke.base.domain.model.po.PermissionsPo;
import com.jhf.youke.base.domain.model.po.PermissionsSetPo;
import com.jhf.youke.base.domain.model.vo.PermissionsVo;
import com.jhf.youke.core.ddd.AbstractDomainService;
import com.jhf.youke.core.entity.PageQuery;
import com.jhf.youke.core.entity.Pagination;
import com.jhf.youke.core.utils.StringUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
import java.util.Optional;


/**
 * @author RHJ
 */
@Service
public class PermissionsService extends AbstractDomainService<PermissionsRepository, PermissionsDo, PermissionsVo> {


    @Resource
    PermissionsConverter permissionsConverter;

    @Resource
    PermissionsSetRepository permissionsSetRepository;


    @Override
    public boolean update(PermissionsDo entity) {
        Optional<PermissionsPo> oldPo = repository.findById(entity.getId());
        if(!entity.getCode().equals(oldPo.get().getCode())){
            //编码已修改
            verifyCode(entity);
            PermissionsSetPo param = new PermissionsSetPo();
            param.setPermissionCode(oldPo.get().getCode());
            List<PermissionsSetPo> list = permissionsSetRepository.findAllMatching(param);
            if(list.size() > 0){
                for(PermissionsSetPo item:list){
                    item.setPermissionCode(entity.getCode());
                }
                permissionsSetRepository.updateBatch(list);
            }
        }
        PermissionsPo permissionsPo = permissionsConverter.do2Po(entity);
        permissionsPo.preUpdate();
        updateParentIds(permissionsPo, true);
        return repository.update(permissionsPo);
    }

    private void verifyCode(PermissionsDo entity) {
        PermissionsPo param = new PermissionsPo();
        param.setCode(entity.getCode());
        List<PermissionsPo> list = repository.findAllMatching(param);
        if(list.size() > 0){
            throw new PermissionsException("权限编码已存在");
        }
    }

    @Override
    public boolean updateBatch(List<PermissionsDo> doList) {
        List<PermissionsPo> poList = permissionsConverter.do2PoList(doList);
        return repository.updateBatch(poList);
    }

    @Override
    public boolean delete(PermissionsDo entity) {
        PermissionsPo permissionsPo = permissionsConverter.do2Po(entity);
        return repository.delete(permissionsPo);
    }

    @Override
    public boolean deleteBatch(List<Long> idList) {
        return repository.deleteBatch(idList);
    }

    @Override
    public boolean insert(PermissionsDo entity) {
        verifyCode(entity);
        PermissionsPo permissionsPo = permissionsConverter.do2Po(entity);
        permissionsPo.preInsert();
        updateParentIds(permissionsPo, false);
        return repository.insert(permissionsPo);
    }

    /**
     * 更新上级ID集合,以及层级
     * @param permissionsPo
     * @return
     */
    private PermissionsPo updateParentIds(PermissionsPo permissionsPo, Boolean isUpdate) {
        String parentTop = "0";
        if(permissionsPo.getParentId() != null && !parentTop.equals(StringUtils.chgNull(permissionsPo.getParentId()))){
            Optional<PermissionsPo> parentPermissions = repository.findById(permissionsPo.getParentId());
            permissionsPo.setParentIds(parentPermissions.get().getParentIds() + "," + permissionsPo.getId());
            permissionsPo.setLayer(parentPermissions.get().getLayer() + 1);
        }else {
            permissionsPo.setParentIds(permissionsPo.getId().toString());
            permissionsPo.setLayer(1);
        }
        if(isUpdate) {
            Optional<PermissionsPo> oldPermissions = repository.findById(permissionsPo.getId());
            if(!oldPermissions.get().getParentId().equals(permissionsPo.getParentId())){
                //此次更新修改了父类ID，则需要更新此记录的下级父类集合
                updateSubParentIds(permissionsPo);
            }
        }
        return permissionsPo;
    }


    /**
     * 更新此记录下级的父类集合
     * @param permissionsPo
     * @return
     */
    private void updateSubParentIds(PermissionsPo permissionsPo) {
        PermissionsPo param = new PermissionsPo();
        param.setParentId(permissionsPo.getId());
        List<PermissionsPo> subList = repository.findAllMatching(param);
        if(subList.size() == 0){
            return;
        }
        for(PermissionsPo item:subList){
            item.setLayer(permissionsPo.getLayer() + 1);
            item.setParentIds(permissionsPo.getParentIds() + "," + permissionsPo.getId());
            repository.update(item);
            updateSubParentIds(item);
        }
    }

    @Override
    public boolean insertBatch(List<PermissionsDo> doList) {
        List<PermissionsPo> poList = permissionsConverter.do2PoList(doList);
        poList = PermissionsPo.getInsertListId(poList);
        return repository.insertBatch(poList);
    }

    @Override
    public Optional<PermissionsVo> findById(Long id) {
        Optional<PermissionsPo> permissionsPo =  repository.findById(id);
        PermissionsVo permissionsVo = permissionsConverter.po2Vo(permissionsPo.orElse(new PermissionsPo()));
        return Optional.ofNullable(permissionsVo);

    }

    @Override
    public boolean remove(Long id) {
        return repository.remove(id);
    }

    @Override
    public boolean removeBatch(List<Long> idList) {
        return repository.removeBatch(idList);
    }

    @Override
    public List<PermissionsVo> findAllMatching(PermissionsDo entity) {
        PermissionsPo permissionsPo = permissionsConverter.do2Po(entity);
        List<PermissionsPo>permissionsPoList =  repository.findAllMatching(permissionsPo);
        return permissionsConverter.po2VoList(permissionsPoList);
    }


    @Override
    public Pagination<PermissionsVo> selectPage(PermissionsDo entity){
        PermissionsPo permissionsPo = permissionsConverter.do2Po(entity);
        PageQuery<PermissionsPo> pageQuery = new PageQuery<>(permissionsPo,entity.getCurrentPage(), entity.getPageSize(), entity.getQuerySort());
        Pagination<PermissionsPo> pagination = repository.selectPage(pageQuery);
        return new Pagination<>(pagination.getPageNum(),pagination.getPageSize(),pagination.getTotalSize(),
                permissionsConverter.po2VoList(pagination.getList()));
    }


}

